#include <iostream>
using namespace std;

class Date {

public:
    Date(int y = 2000, int m = 1, int d = 1) 
        :_y(y)
        ,_m(m)
        ,_d(d)
    {
        std::cout << "Date create" << std::endl;
    }

    ~Date() {
        std::cout << "Data destroy" << std::endl;
    }

    void print() {
        std::cout << "year: " << _y << " month: " << _m << " day: " << _d << std::endl;
    }

private:
    int _y;
    int _m;
    int _d;
};

namespace myPtr {

    template <class T>
    class shared_ptr {
    public:
        // 构造
        explicit shared_ptr(T* ptr = nullptr) 
            :_ptr(ptr)
            ,_pcount(new int(1))
        {}

        // 拷贝构造
        shared_ptr(const shared_ptr<T>& sp) 
            :_ptr(sp._ptr)
            ,_pcount(sp._pcount)
        {
            ++(*_pcount);
        }

        // 赋值重载
        shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
            if(_ptr != sp._ptr) {
                if(--(*_pcount) == 0) {
                    delete _ptr;
                    delete _pcount;
                }
                
                _ptr = sp._ptr;
                _pcount = sp._pcount;
                (*_pcount)++;
            }
            return *this;
        }

        // 析构
        ~shared_ptr() {
            if(--(*_pcount) == 0) {
                delete _ptr;
                delete _pcount;
            }
        }

        // 成员函数

        T& operator*() {
            return *_ptr;
        }
        
        // sp-> --> T*
        // T*-> --> val
        // (sp->)->val
        T* operator->() {
            return _ptr;
        }

        T* get() {
            return _ptr;
        }

        int use_count() {
            return *(_pcount);
        }

    private:
        T* _ptr;
        int* _pcount;
    };
}

int main() {
    myPtr::shared_ptr<Date> sp1(new Date);
    myPtr::shared_ptr<Date> sp2(sp1);
    // 2
    std::cout << "sp1/sp2 use_count: " << sp1.use_count() << std::endl;

    myPtr::shared_ptr<Date> sp3(new Date(2025, 10, 9));
    sp1 = sp3;
    // 2
    std::cout << "sp1/sp3 use_count: " << sp1.use_count() << std::endl;
    // 1
    std::cout << "sp2 use_count: " << sp2.use_count() << std::endl;
    return 0;
}